// 数据处理模块
// 负责处理文件扫描结果，生成搜索索引，管理JSON数据

const fs = require('fs').promises;
const path = require('path');
const config = require('../config/config');
const nodejieba = require('nodejieba');

class DataProcessor {
  constructor() {
    this.searchIndex = {         // 搜索索引
      nameIndex: {},             // 文件名索引
      pathIndex: {},             // 路径索引
      typeIndex: {}              // 类型索引
    };
  }

  /**
   * 处理扫描结果并保存到JSON文件
   * @param {Object} scanResult - 文件扫描结果
   * @returns {Promise<string>} 保存的文件路径
   */
  async processScanResult(scanResult) {
    console.log('开始处理扫描结果...');
    
    try {
      // 加载上次的数据进行比较
      let previousData = null;
      try {
        previousData = await this.loadJsonFile();
      } catch (error) {
        console.log('无上次扫描数据，跳过比较');
      }
      
      // 构建搜索索引
      this.buildSearchIndex(scanResult.files);
      
      // 优化数据结构
      const optimizedData = this.optimizeDataStructure(scanResult, previousData);
      
      // 添加搜索索引到结果中
      optimizedData.searchIndex = this.searchIndex;
      
      // 保存到JSON文件
      const savedPath = await this.saveToJsonFile(optimizedData);
      
      console.log(`数据处理完成，已保存到: ${savedPath}`);
      return savedPath;
      
    } catch (error) {
      console.error('处理扫描结果时发生错误:', error);
      throw error;
    }
  }

  /**
   * 构建搜索索引
   * @param {Array} files - 文件列表
   */
  buildSearchIndex(files) {
    console.log('构建搜索索引...');
    
    // 重置索引
    this.searchIndex = {
      nameIndex: {},
      pathIndex: {},
      typeIndex: {}
    };

    files.forEach(file => {
      const fileId = file.id;
      
      // 构建文件名索引（支持分词搜索）
      this.buildNameIndex(file.name, fileId);
      
      // 构建路径索引
      this.buildPathIndex(file.path, fileId);
      
      // 构建类型索引
      this.buildTypeIndex(file.type, fileId);
    });

    console.log(`搜索索引构建完成，包含 ${Object.keys(this.searchIndex.nameIndex).length} 个名称关键词`);
  }

  /**
   * 构建文件名索引
   * @param {string} fileName - 文件名
   * @param {string} fileId - 文件ID
   */
  buildNameIndex(fileName, fileId) {
    // 提取文件名（不包括扩展名）
    const nameWithoutExt = path.parse(fileName).name;
    
    // 分词处理 - 支持中文和英文
    const keywords = this.extractKeywords(nameWithoutExt);
    
    keywords.forEach(keyword => {
      if (!this.searchIndex.nameIndex[keyword]) {
        this.searchIndex.nameIndex[keyword] = [];
      }
      
      // 避免重复添加
      if (!this.searchIndex.nameIndex[keyword].includes(fileId)) {
        this.searchIndex.nameIndex[keyword].push(fileId);
      }
    });
  }

  /**
   * 构建路径索引
   * @param {string} filePath - 文件路径
   * @param {string} fileId - 文件ID
   */
  buildPathIndex(filePath, fileId) {
    // 将路径分解为各个部分
    const pathParts = filePath.split(path.sep).filter(part => part);
    
    pathParts.forEach(part => {
      const keywords = this.extractKeywords(part);
      
      keywords.forEach(keyword => {
        if (!this.searchIndex.pathIndex[keyword]) {
          this.searchIndex.pathIndex[keyword] = [];
        }
        
        if (!this.searchIndex.pathIndex[keyword].includes(fileId)) {
          this.searchIndex.pathIndex[keyword].push(fileId);
        }
      });
    });
  }

  /**
   * 构建类型索引
   * @param {string} fileType - 文件类型
   * @param {string} fileId - 文件ID
   */
  buildTypeIndex(fileType, fileId) {
    if (!this.searchIndex.typeIndex[fileType]) {
      this.searchIndex.typeIndex[fileType] = [];
    }
    
    this.searchIndex.typeIndex[fileType].push(fileId);
  }

  /**
   * 提取关键词（支持智能中文分词）
   * @param {string} text - 要处理的文本
   * @returns {Array} 关键词数组
   */
  extractKeywords(text) {
    if (!text) return [];
    
    const keywords = new Set();
    
    // 转换为小写
    const lowerText = text.toLowerCase();
    
    // 使用jieba进行智能分词
    try {
      const segments = nodejieba.cut(lowerText);
      segments.forEach(segment => {
        if (segment.trim() && segment.length > 0) {
          keywords.add(segment.trim());
        }
      });
    } catch (error) {
      console.warn('Jieba分词失败，使用备用分词方案:', error.message);
    }
    
    // 备用分词方案：按特殊字符分割
    const parts = lowerText.split(/[\s\-_\.，。、（）\(\)【】\[\]]+/).filter(part => part);
    
    parts.forEach(part => {
      // 添加完整部分
      if (part.length > 0) {
        keywords.add(part);
      }
      
      // 对于中文，使用jieba分词 + 字符级别索引
      if (this.containsChinese(part)) {
        try {
          // jieba分词
          const chineseSegments = nodejieba.cut(part);
          chineseSegments.forEach(seg => {
            if (seg.trim()) {
              keywords.add(seg.trim());
            }
          });
        } catch (error) {
          // 如果jieba失败，回退到字符级别索引
          console.warn('中文分词失败，使用字符级别索引:', error.message);
        }
        
        // 添加单字索引（用于部分匹配）
        for (let i = 0; i < part.length; i++) {
          if (part[i].trim()) {
            keywords.add(part[i]);
          }
          
          // 添加2-3字的组合
          if (i < part.length - 1) {
            keywords.add(part.substr(i, 2));
          }
          if (i < part.length - 2) {
            keywords.add(part.substr(i, 3));
          }
        }
      }
      
      // 对于英文，添加前缀索引
      if (this.containsEnglish(part) && part.length > 2) {
        for (let i = 2; i <= part.length; i++) {
          keywords.add(part.substr(0, i));
        }
      }
    });
    
    // 过滤掉过短的关键词和标点符号
    const filtered = Array.from(keywords).filter(keyword => {
      return keyword.length > 0 && 
             !/^[\s\-_\.，。、（）\(\)【】\[\]]+$/.test(keyword) &&
             keyword.length >= 1; // 至少1个字符
    });
    
    return filtered;
  }

  /**
   * 检查文本是否包含中文
   * @param {string} text - 要检查的文本
   * @returns {boolean} 是否包含中文
   */
  containsChinese(text) {
    return /[\u4e00-\u9fff]/.test(text);
  }

  /**
   * 检查文本是否包含英文
   * @param {string} text - 要检查的文本
   * @returns {boolean} 是否包含英文
   */
  containsEnglish(text) {
    return /[a-zA-Z]/.test(text);
  }

  /**
   * 优化数据结构
   * @param {Object} scanResult - 原始扫描结果
   * @returns {Object} 优化后的数据结构
   */
  optimizeDataStructure(scanResult, previousData = null) {
    console.log('优化数据结构...');
    
    // 对文件按名称排序
    const sortedFiles = scanResult.files.sort((a, b) => 
      a.name.localeCompare(b.name, 'zh-CN')
    );
    
    // 对文件夹按名称排序
    const sortedFolders = scanResult.folders.sort((a, b) => 
      a.name.localeCompare(b.name, 'zh-CN')
    );
    
    // 计算与上次扫描的变化对比
    const changes = this.calculateChanges(scanResult.statistics, previousData);
    
    // 优化统计信息
    const enhancedStatistics = this.enhanceStatistics(scanResult.statistics, changes);
    
    return {
      metadata: {
        ...scanResult.metadata,
        optimizedAt: new Date().toISOString(),
        indexSize: this.calculateIndexSize(),
        changes: changes
      },
      files: sortedFiles,
      folders: sortedFolders,
      tree: scanResult.tree,
      statistics: enhancedStatistics
    };
  }

  /**
   * 计算与上次扫描的变化对比
   * @param {Object} currentStats - 当前统计信息
   * @param {Object} previousData - 上次扫描数据
   * @returns {Object} 变化对比信息
   */
  calculateChanges(currentStats, previousData) {
    if (!previousData || !previousData.statistics) {
      return {
        filesChanged: 0,
        foldersChanged: 0,
        isFirstScan: true
      };
    }

    const prevStats = previousData.statistics;
    
    return {
      filesChanged: (currentStats.totalFiles || 0) - (prevStats.totalFiles || 0),
      foldersChanged: (currentStats.totalFolders || 0) - (prevStats.totalFolders || 0),
      sizeChanged: (currentStats.totalSize || 0) - (prevStats.totalSize || 0),
      isFirstScan: false,
      previousScanTime: previousData.metadata?.lastUpdate
    };
  }

  /**
   * 增强统计信息
   * @param {Object} originalStats - 原始统计信息
   * @param {Object} changes - 变化信息
   * @returns {Object} 增强的统计信息
   */
  enhanceStatistics(originalStats, changes = {}) {
    // 计算格式化的总大小
    const totalSizeFormatted = this.formatFileSize(originalStats.totalSize);
    const averageFileSizeFormatted = this.formatFileSize(originalStats.averageFileSize);
    
    // 按文件类型排序
    const sortedFileTypes = Object.entries(originalStats.fileTypes)
      .sort(([,a], [,b]) => b - a)
      .reduce((obj, [key, value]) => {
        obj[key] = value;
        return obj;
      }, {});
    
    return {
      ...originalStats,
      totalSizeFormatted,
      averageFileSizeFormatted,
      fileTypes: sortedFileTypes,
      searchKeywords: Object.keys(this.searchIndex.nameIndex).length
    };
  }

  /**
   * 计算索引大小
   * @returns {Object} 索引大小信息
   */
  calculateIndexSize() {
    return {
      nameKeywords: Object.keys(this.searchIndex.nameIndex).length,
      pathKeywords: Object.keys(this.searchIndex.pathIndex).length,
      typeKeywords: Object.keys(this.searchIndex.typeIndex).length,
      totalKeywords: Object.keys(this.searchIndex.nameIndex).length + 
                    Object.keys(this.searchIndex.pathIndex).length + 
                    Object.keys(this.searchIndex.typeIndex).length
    };
  }

  /**
   * 保存数据到JSON文件
   * @param {Object} data - 要保存的数据
   * @returns {Promise<string>} 保存的文件路径
   */
  async saveToJsonFile(data) {
    const filePath = config.scan.indexFile;
    
    try {
      // 确保目录存在
      const dir = path.dirname(filePath);
      await fs.mkdir(dir, { recursive: true });
      
      // 生成JSON字符串（格式化以便调试）
      const jsonString = JSON.stringify(data, null, 2);
      
      // 保存到文件
      await fs.writeFile(filePath, jsonString, 'utf8');
      
      // 记录文件大小
      const stats = await fs.stat(filePath);
      console.log(`索引文件已保存: ${filePath} (${this.formatFileSize(stats.size)})`);
      
      return filePath;
      
    } catch (error) {
      console.error('保存JSON文件时发生错误:', error);
      throw error;
    }
  }

  /**
   * 加载JSON索引文件
   * @returns {Promise<Object>} 加载的数据
   */
  async loadJsonFile() {
    const filePath = config.scan.indexFile;
    
    try {
      // 检查文件是否存在
      await fs.access(filePath, fs.constants.F_OK);
      
      // 读取文件内容
      const jsonString = await fs.readFile(filePath, 'utf8');
      const data = JSON.parse(jsonString);
      
      // 恢复搜索索引
      if (data.searchIndex) {
        this.searchIndex = data.searchIndex;
      }
      
      console.log(`索引文件加载成功: ${filePath}`);
      return data;
      
    } catch (error) {
      if (error.code === 'ENOENT') {
        console.log('索引文件不存在，需要先进行扫描');
        return null;
      } else {
        console.error('加载JSON文件时发生错误:', error);
        throw error;
      }
    }
  }

  /**
   * 执行搜索
   * @param {string} keyword - 搜索关键词
   * @param {Object} options - 搜索选项
   * @returns {Array} 搜索结果文件ID数组
   */
  search(keyword, options = {}) {
    if (!keyword || keyword.trim().length === 0) {
      return [];
    }
    
    const {
      searchType = 'all',    // 搜索类型: name, path, all
      fileType = 'all',      // 文件类型过滤
      maxResults = config.ui.maxSearchResults
    } = options;
    
    // 解析搜索关键词（支持引号精确匹配和多关键词）
    const searchTerms = this.parseSearchTerms(keyword);
    console.log('解析的搜索关键词:', searchTerms);
    
    if (searchTerms.length === 0) {
      return [];
    }
    
    // 如果只有一个关键词，使用原有的搜索逻辑
    if (searchTerms.length === 1) {
      return this.singleTermSearch(searchTerms[0], searchType, fileType, maxResults);
    }
    
    // 多关键词AND逻辑搜索
    return this.multiTermAndSearch(searchTerms, searchType, fileType, maxResults);
  }

  /**
   * 解析搜索关键词，支持引号精确匹配和智能分词
   * @param {string} keyword - 原始搜索关键词
   * @returns {Array} 解析后的关键词数组
   */
  parseSearchTerms(keyword) {
    const terms = [];
    let current = '';
    let inQuotes = false;
    let quoteChar = '';
    
    // 第一步：处理引号和空格分隔
    for (let i = 0; i < keyword.length; i++) {
      const char = keyword[i];
      
      if ((char === '"' || char === "'") && !inQuotes) {
        // 开始引号
        inQuotes = true;
        quoteChar = char;
      } else if (char === quoteChar && inQuotes) {
        // 结束引号
        inQuotes = false;
        quoteChar = '';
        if (current.trim()) {
          terms.push({ text: current.trim().toLowerCase(), exact: true });
          current = '';
        }
      } else if (char === ' ' && !inQuotes) {
        // 空格分隔（非引号内）
        if (current.trim()) {
          this.addParsedTerm(terms, current.trim().toLowerCase(), false);
          current = '';
        }
      } else {
        current += char;
      }
    }
    
    // 处理最后一个词
    if (current.trim()) {
      this.addParsedTerm(terms, current.trim().toLowerCase(), inQuotes);
    }
    
    return terms;
  }

  /**
   * 添加解析后的搜索词，支持jieba智能分词
   * @param {Array} terms - 词条数组
   * @param {string} text - 文本
   * @param {boolean} exact - 是否精确匹配
   */
  addParsedTerm(terms, text, exact) {
    if (exact) {
      // 精确匹配模式：不进行分词
      terms.push({ text: text, exact: true });
      return;
    }
    
    // 非精确匹配：尝试智能分词
    if (this.containsChinese(text)) {
      try {
        const segments = nodejieba.cut(text);
        if (segments.length > 1) {
          // 如果分词结果有多个词，添加每个分词结果
          segments.forEach(segment => {
            if (segment.trim() && segment.length > 0) {
              terms.push({ text: segment.trim(), exact: false });
            }
          });
          return;
        }
      } catch (error) {
        console.warn('搜索词分词失败:', error.message);
      }
    }
    
    // 如果分词失败或者不是中文，直接添加原词
    terms.push({ text: text, exact: false });
  }

  /**
   * 单关键词搜索（带相关度排序）
   */
  singleTermSearch(searchTerm, searchType, fileType, maxResults) {
    const matchedFileIds = new Map(); // ID -> {nameMatches: boolean, pathMatches: boolean}
    
    // 根据搜索类型执行搜索
    if (searchType === 'name' || searchType === 'all') {
      const nameMatches = this.searchInIndex(this.searchIndex.nameIndex, searchTerm.text, searchTerm.exact);
      nameMatches.forEach(id => {
        const existing = matchedFileIds.get(id) || {nameMatches: false, pathMatches: false};
        existing.nameMatches = true;
        matchedFileIds.set(id, existing);
      });
    }
    
    if (searchType === 'path' || searchType === 'all') {
      const pathMatches = this.searchInIndex(this.searchIndex.pathIndex, searchTerm.text, searchTerm.exact);
      pathMatches.forEach(id => {
        const existing = matchedFileIds.get(id) || {nameMatches: false, pathMatches: false};
        existing.pathMatches = true;
        matchedFileIds.set(id, existing);
      });
    }
    
    // 计算相关度评分并排序
    const scoredResults = Array.from(matchedFileIds.keys()).map(fileId => {
      const matchInfo = matchedFileIds.get(fileId);
      let score = 0;
      
      // 文件名匹配权重更高
      if (matchInfo.nameMatches) {
        score += searchTerm.exact ? 10 : 5;
      }
      
      // 路径匹配权重较低
      if (matchInfo.pathMatches) {
        score += searchTerm.exact ? 3 : 1;
      }
      
      return { fileId, score };
    });
    
    // 按相关度排序（分数越高越相关）
    scoredResults.sort((a, b) => b.score - a.score);
    
    const sortedFileIds = scoredResults.map(item => item.fileId);
    
    return this.filterAndLimitResults(sortedFileIds, fileType, maxResults);
  }

  /**
   * 多关键词AND逻辑搜索（带相关度排序）
   */
  multiTermAndSearch(searchTerms, searchType, fileType, maxResults) {
    // 为每个关键词获取匹配的文件ID和匹配信息
    const termResults = searchTerms.map(term => {
      const matchedIds = new Map(); // ID -> {nameMatches: boolean, pathMatches: boolean}
      
      if (searchType === 'name' || searchType === 'all') {
        const nameMatches = this.searchInIndex(this.searchIndex.nameIndex, term.text, term.exact);
        nameMatches.forEach(id => {
          const existing = matchedIds.get(id) || {nameMatches: false, pathMatches: false};
          existing.nameMatches = true;
          matchedIds.set(id, existing);
        });
      }
      
      if (searchType === 'path' || searchType === 'all') {
        const pathMatches = this.searchInIndex(this.searchIndex.pathIndex, term.text, term.exact);
        pathMatches.forEach(id => {
          const existing = matchedIds.get(id) || {nameMatches: false, pathMatches: false};
          existing.pathMatches = true;
          matchedIds.set(id, existing);
        });
      }
      
      return { term, matchedIds };
    });
    
    // 找到所有关键词的交集（AND逻辑）
    if (termResults.length === 0) {
      return [];
    }
    
    let intersection = new Set(termResults[0].matchedIds.keys());
    for (let i = 1; i < termResults.length; i++) {
      intersection = new Set([...intersection].filter(x => termResults[i].matchedIds.has(x)));
    }
    
    // 计算相关度评分并排序
    const scoredResults = Array.from(intersection).map(fileId => {
      const score = this.calculateRelevanceScore(fileId, searchTerms, termResults);
      return { fileId, score };
    });
    
    // 按相关度排序（分数越高越相关）
    scoredResults.sort((a, b) => b.score - a.score);
    
    const sortedFileIds = scoredResults.map(item => item.fileId);
    
    return this.filterAndLimitResults(sortedFileIds, fileType, maxResults);
  }

  /**
   * 计算搜索结果相关度评分
   * @param {string} fileId - 文件ID
   * @param {Array} searchTerms - 搜索词
   * @param {Array} termResults - 词匹配结果
   * @returns {number} 相关度分数
   */
  calculateRelevanceScore(fileId, searchTerms, termResults) {
    let score = 0;
    
    // 基础分数：每个匹配的关键词贡献分数
    termResults.forEach(({ term, matchedIds }) => {
      const matchInfo = matchedIds.get(fileId);
      if (matchInfo) {
        // 文件名匹配权重更高
        if (matchInfo.nameMatches) {
          score += term.exact ? 10 : 5; // 精确匹配权重更高
        }
        
        // 路径匹配权重较低
        if (matchInfo.pathMatches) {
          score += term.exact ? 3 : 1;
        }
      }
    });
    
    // 奖励分数：完全匹配的关键词数量
    const matchedTermCount = termResults.filter(({ matchedIds }) => matchedIds.has(fileId)).length;
    score += matchedTermCount * 2;
    
    // 奖励分数：关键词在文件名中的位置（越靠前分数越高）
    try {
      // 这里可以添加更复杂的位置评分逻辑
      // 目前使用简单的匹配计数
    } catch (error) {
      console.warn('计算位置评分失败:', error.message);
    }
    
    return score;
  }

  /**
   * 过滤和限制搜索结果
   */
  filterAndLimitResults(results, fileType, maxResults) {
    // 文件类型过滤
    if (fileType !== 'all' && this.searchIndex.typeIndex[fileType]) {
      const typeFileIds = new Set(this.searchIndex.typeIndex[fileType]);
      results = results.filter(id => typeFileIds.has(id));
    }
    
    // 限制结果数量
    if (results.length > maxResults) {
      results = results.slice(0, maxResults);
    }
    
    return results;
  }

  /**
   * 在索引中搜索
   * @param {Object} index - 要搜索的索引
   * @param {string} searchTerm - 搜索词
   * @param {boolean} exact - 是否精确匹配
   * @returns {Array} 匹配的文件ID数组
   */
  searchInIndex(index, searchTerm, exact = false) {
    const matches = [];
    
    if (exact) {
      // 精确匹配模式：只匹配完全相同的关键词
      if (index[searchTerm]) {
        matches.push(...index[searchTerm]);
      }
    } else {
      // 模糊匹配模式：包含匹配
      // 先精确匹配
      if (index[searchTerm]) {
        matches.push(...index[searchTerm]);
      }
      
      // 再模糊匹配
      Object.keys(index).forEach(key => {
        if (key.includes(searchTerm) && key !== searchTerm) {
          matches.push(...index[key]);
        }
      });
    }
    
    // 去重
    return [...new Set(matches)];
  }

  /**
   * 根据文件ID获取文件信息
   * @param {Array} fileIds - 文件ID数组
   * @param {Array} allFiles - 所有文件数据
   * @returns {Array} 匹配的文件信息数组
   */
  getFilesByIds(fileIds, allFiles) {
    const fileMap = new Map();
    allFiles.forEach(file => {
      fileMap.set(file.id, file);
    });
    
    return fileIds
      .map(id => fileMap.get(id))
      .filter(file => file); // 过滤掉不存在的文件
  }

  /**
   * 格式化文件大小
   * @param {number} bytes - 字节数
   * @returns {string} 格式化后的大小
   */
  formatFileSize(bytes) {
    if (bytes === 0) return '0 B';
    
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  /**
   * 获取索引统计信息
   * @returns {Object} 索引统计信息
   */
  getIndexStats() {
    return {
      searchIndex: this.calculateIndexSize(),
      lastUpdated: new Date().toISOString(),
      isLoaded: Object.keys(this.searchIndex.nameIndex).length > 0
    };
  }

  /**
   * 清理索引
   */
  clearIndex() {
    this.searchIndex = {
      nameIndex: {},
      pathIndex: {},
      typeIndex: {}
    };
    console.log('搜索索引已清理');
  }
}

module.exports = DataProcessor;